package com.platform.comm.common.batch;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.google.common.collect.Maps;
import com.platform.comm.common.service.ComImportService;
import com.platform.comm.entity.CommBatchInfoEntity;
import com.platform.comm.entity.CommDataInfoEntity;
import com.platform.comm.service.ICommBatchInfoBiz;
import com.platform.comm.service.ICommDataInfoBiz;
import com.platform.comm.util.DateTimeUtil;
import com.platform.comm.util.SpringBeansUtil;
import com.platform.comm.util.StringUtil;
import com.platform.vo.BatchResult;
import com.platform.vo.ExcelCfgDto;
import com.platform.vo.ImportDto;
import com.platform.enums.BatchJobStatus;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;


/**
 * Description: 上下文
 *
 * @author lx Created on 2020/01/06
 **/
@Log4j2
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@JsonIgnoreProperties()
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ComBatchContext implements Serializable {
    @JsonIgnore
    private final ICommDataInfoBiz commDataImpBiz;
    @Getter
    @JsonIgnore
    private ComImportService comImportService;

    @JsonIgnore
    private final ICommBatchInfoBiz dirBatchInfoBiz;

    @Getter
    @JsonIgnore
    private ExcelCfgDto importConfig;

    @Getter
    private CommDataInfoEntity commDataInfoEntity;
    @Getter
    private CommBatchInfoEntity commBatchInfoEntity;
    @Getter
    private BatchResult batchResult = new BatchResult();

    @Getter
    private Map<String, String> params = Maps.newHashMap();
    @Getter
    private Map<String, Object> defaultFields = Maps.newHashMap();
    @Getter
    private Map<String, String> fieldMapper = Maps.newHashMap();

    public ComBatchContext(ICommDataInfoBiz commDataImpBiz, ICommBatchInfoBiz dirBatchInfoBiz) {
        this.commDataImpBiz = commDataImpBiz;
        this.dirBatchInfoBiz = dirBatchInfoBiz;
    }

    public Map<String, String> translateExport(ImportDto item) {
        return this.comImportService.translateExport(this, item);
    }

    public ImportDto repeatImport(ImportDto item) {
        return comImportService.repeatImport(this, item);
    }

    /**
     * 初始化上传数据的信息
     *
     * @param importId 批次id
     * @return 返回当前上下文
     */
    public ComBatchContext bindCommonData(String importId) {
        commDataInfoEntity = commDataImpBiz.initCommDataInfo(importId);
        return this;
    }

    /**
     * 初始化配置信息
     */
    public void build() {
        bindService();
    }

    /**
     * 关联具体业务层实现类
     */
    private void bindService() {
        String moduleName = params.get("moduleName");
        String bizType = StringUtils.substringBefore(moduleName, "Controller") + "ImportServiceImpl";
        this.comImportService =  (ComImportService) SpringBeansUtil.getBean(bizType);
    }

    /**
     * 绑定参数
     *
     * @param parameterMap 参数
     * @return 返回上下文
     */
    public ComBatchContext bindParams(Map<String, String> parameterMap) {
        this.params.putAll(parameterMap);
        return this;
    }

    /**
     * 初始化配置导入的配置
     *
     * @param moduleName 模块名
     */
    public ComBatchContext buildConfig(String moduleName) {
        String module = StringUtils.substringBefore(moduleName, "Controller");
        this.importConfig = commDataImpBiz.initImpConfig(module,ICommDataInfoBiz.IMPORT);

        return this;
    }

    /**
     * 数据转换 根据不同的业务实现不同的转换
     *
     * @param item 参数
     */
    public void translateImport(ImportDto item) {
        comImportService.translateImport(this, item);
    }

    /**
     * 数据校验
     *
     * @param item 数据
     */
    public void validateImport(ImportDto item) {
        comImportService.validateImport(this, item);
    }

    /**
     * 初始化 任务记录表
     * @param jobId 任务id
     * @return 返回任务实体类
     */
    public CommBatchInfoEntity getNewCommBatchEntity(Long jobId) {
        commBatchInfoEntity = new CommBatchInfoEntity();
        commBatchInfoEntity.setId(StringUtil.getUUID());
        commBatchInfoEntity.setCommDataId(this.commDataInfoEntity.getId());
        commBatchInfoEntity.setDelflag("1");
        commBatchInfoEntity.setJobType(comImportService.getImportType());
        commBatchInfoEntity.setCreateDept(commDataInfoEntity.getUploadDept());
        commBatchInfoEntity.setCreateBy(commDataInfoEntity.getUploadUser());
        commBatchInfoEntity.setJobStatus(BatchJobStatus.STARTED.code);
        commBatchInfoEntity.setCreateDate(DateTimeUtil.toStdLongTimeStr(LocalDateTime.now()));
        commBatchInfoEntity.setJobName(comImportService.getName());
        commBatchInfoEntity.setCreateName(commDataInfoEntity.getUploadUserName());
        commBatchInfoEntity.setCreateDeptName(commDataInfoEntity.getUploadOrgName());
        this.commBatchInfoEntity.setJobId(String.valueOf(jobId));
        return this.commBatchInfoEntity;
    }

    /**
     * 更新记录信息
     */
    public void finishImportJob() {
        //清除
        this.clearRedis();
        //更新数据状态
        this.commBatchInfoEntity.setTotalCount(BigDecimal.valueOf(this.getBatchResult().getTotalCount()));
        this.commBatchInfoEntity.setValidationCount(BigDecimal.valueOf(this.getBatchResult().getErrorCount()));
        this.commBatchInfoEntity.setCachedCount(BigDecimal.valueOf(this.getBatchResult().getCachedCount()));
        this.commBatchInfoEntity.setSkippedCount(BigDecimal.valueOf(this.getBatchResult().getSkippedCount()));
        this.commBatchInfoEntity.setJobStatus(BatchJobStatus.COMPLETED.code);
        this.commBatchInfoEntity.setFinishDate(DateTimeUtil.toStdLongTimeStr(LocalDateTime.now()));
        if (this.getBatchResult().getErrorCount() > 0) {
            this.commBatchInfoEntity.setJobResult(this.commDataInfoEntity.getErrorUrl());
        }
        this.dirBatchInfoBiz.saveEntity(this.commBatchInfoEntity);
    }

    /**
     * 任务完成够清除redis缓存
     */
    private void clearRedis() {
        comImportService.clearRedis();
    }

    /**
     * 更新记录信息
     */
    public void finishImportErrorJob() {
        this.commBatchInfoEntity.setTotalCount(BigDecimal.valueOf(this.getBatchResult().getTotalCount()));
        this.commBatchInfoEntity.setValidationCount(BigDecimal.ZERO);
        this.commBatchInfoEntity.setCachedCount(BigDecimal.ZERO);
        this.commBatchInfoEntity.setSkippedCount(BigDecimal.ZERO);
        this.commBatchInfoEntity.setJobStatus(BatchJobStatus.FAILED.code);
        this.dirBatchInfoBiz.saveEntity(this.commBatchInfoEntity);
    }
}
